﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Speech.Recognition;
using Microsoft.Speech.AudioFormat;
using Microsoft.Kinect;
using System.Windows.Threading;
using System.Windows;
using System.Windows.Media;
using System.Diagnostics;

namespace KinaestheticDebuggerEnvironment
{
    partial class Page2
    {

        private void InitializeKinectSpeech()
        {

            speechRecognizer = speechRec.CreateSpeechRecognizer();
            speechRec.OnSpeechDetected += OnSpeechDetected;
            speechRec.OnSpeechAccepted += OnSpeechAccepted;
            speechRec.OnSpeechTilt += OnSpeechTilt;

            if (speechRecognizer == null)
            {
                tbSpeechStatus.Text = ("There was a problem initializing Speech Recognition. Failed to load Speech SDK");
            }

            if (speechRecognizer != null && kinectSensor != null)
            {
                // NOTE: Need to wait 4 seconds for device to be ready to stream audio right after initialization
                tbSpeechStatus.Text = ("Initializing audio stream...");
                this.readyTimer = new DispatcherTimer();
                this.readyTimer.Tick += this.ReadyTimerTick;
                this.readyTimer.Interval = new TimeSpan(0, 0, 4);
                this.readyTimer.Start();
               
                //this.UpdateInstructionsText(string.Empty);

            }

        }

        //private void EnableAecChecked(object sender, RoutedEventArgs e)
        //{
        //    CheckBox enableAecCheckBox = (CheckBox)sender;
        //    if (enableAecCheckBox.IsChecked != null)
        //    {
        //        this.kinect.AudioSource.EchoCancellationMode = enableAecCheckBox.IsChecked.Value
        //                                                     ? EchoCancellationMode.CancellationAndSuppression
        //                                                     : EchoCancellationMode.None;
        //    }
        //}

        private void ReadyTimerTick(object sender, EventArgs e)
        {
            this.Start();
            tbSpeechStatus.Text = ("Ready to recognize speech!");
            this.readyTimer.Stop();
            this.readyTimer = null;
        }

        private void Start()
        {
            var audioSource = this.kinectSensor.AudioSource;
            audioSource.BeamAngleMode = BeamAngleMode.Adaptive;
            var kinectStream = audioSource.Start();
            
            speechRecognizer.SetInputToAudioStream(
                kinectStream, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
            speechRecognizer.RecognizeAsync(RecognizeMode.Multiple);
        }

        void OnSpeechAccepted(string speech)
        {
            map.SpeechMapping(ide, speech);

            //int pos = detectedGestures.Items.Add(string.Format("Speech: {0}", speech));
            //detectedGestures.SelectedIndex = pos;
            detectedCommandsTextBlock.Text = "Speech: " + speech;
        }

        void OnSpeechDetected(string speech)
        {
            tbSpeechStatus.Text = speech;
            if(speech.Contains("Recognized"))
            {
                tbSpeechStatus.Foreground = new SolidColorBrush(Colors.Green);
            }
            else if (speech.Contains("Rejected"))
            {
                tbSpeechStatus.Foreground = new SolidColorBrush(Colors.Red);
            }
            else
            {
                tbSpeechStatus.Foreground = new SolidColorBrush(Colors.Black);
            }
        }

        void OnSpeechTilt(string speech)
        {
            
            if (kinectSensor != null && kinectSensor.IsRunning)
            {
                tbSpeechStatus.Text = speech;
                tbInstructions.Text = "Say: Kinect Up || Kinect Down";
                //int pos;
                int elevationAngle = kinectSensor.ElevationAngle;
                Debug.WriteLine("maxangle:{0}", kinectSensor.MaxElevationAngle);
                Debug.WriteLine("minangle:{0}", kinectSensor.MinElevationAngle);
                Debug.WriteLine(elevationAngle);
                switch (speech)
                {
                    case "KINECT UP":
                        //pos = detectedGestures.Items.Add(string.Format("Speech: {0}", speech));
                        //detectedGestures.SelectedIndex = pos;
                        detectedCommandsTextBlock.Text = "Speech: " + speech;
                        //Check if kinect is at maximum angle
                        if (elevationAngle < kinectSensor.MaxElevationAngle - 2)
                        {
                            try
                            {
                                kinectSensor.ElevationAngle = elevationAngle + 3;
                                //tbInstructions.Text = "Kinect current angle: "+elevationAngle;
                            }
                            catch (Exception e)
                            {
                                Debug.WriteLine("Error tilting kinect up: {0}", e);
                            }
                        }
                        else
                        {
                            tbInstructions.Text = "Kinect reached the maximum angle!";
                        }
                        break;
                    case "KINECT DOWN":
                        //pos = detectedGestures.Items.Add(string.Format("Speech: {0}", speech));
                        //detectedGestures.SelectedIndex = pos;
                        detectedCommandsTextBlock.Text = "Speech: " + speech;
                        //Check if kinect is at minimum angle
                        if (elevationAngle > kinectSensor.MinElevationAngle + 2)
                        {
                            try
                            {
                                kinectSensor.ElevationAngle = elevationAngle - 3;
                                //tbInstructions.Text = "Kinect current angle: " + elevationAngle;
                            }
                            catch (Exception e)
                            {
                                Debug.WriteLine("Error tilting kinect up: {0}", e);
                            }
                            
                        }
                        else
                        {
                            tbInstructions.Text = "Kinect reached the minimum angle!";
                        }
                        break;
                }
                //Do not change Elevation Angle often, please see documentation on this and Kinect Explorer for a robust example
                System.Threading.Thread.Sleep(new TimeSpan(hours: 0, minutes: 0, seconds: 1));
            }
        }
    }
}
